//
//  vhECGFiltersLib.m
//  CPETvhECGService
//
//  Created by moon_zm on 2024/9/12.
//

#import "vhECGFiltersLib.h"
#import <vhStressTemplLib/vhStressTemplLib-Swift.h>

@interface vhECGFiltersLib ()
@property (nonatomic, strong) vhFiltersLib *filterLab;//心电滤波对象
@property (nonatomic, strong) vhMeanRRmsLib *meanRRmsLab;//心率分析对象

@property (nonatomic, assign) int ecgRate;//采样率
@property (nonatomic, assign) int freq_low;//低通滤波
@property (nonatomic, assign) int freq_notch;//工频滤波
@property (nonatomic, assign) int smoothStrength;//肌电滤波
@property (nonatomic, assign) BOOL isOpen; //default is YES
@property (nonatomic, assign) double uVpb; //default is 1.0
@property (nonatomic, strong) NSMutableArray<NSMutableArray<NSNumber *> *> *bufferData;

@end

@implementation vhECGFiltersLib

+ (instancetype)shared {
    static vhECGFiltersLib *identifier = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        identifier = [[vhECGFiltersLib alloc] init];
    });
    return identifier;
}

- (instancetype)init {
    if (self = [super init]) {
        self.ecgRate = 500;
        self.freq_low = 40;
        self.freq_notch = 50;
        self.smoothStrength = 2;
        self.isOpen = YES;
        self.uVpb = 1.0;
        //创建滤波器
        self.filterLab = [[vhFiltersLib alloc] initWithMe:@"hspecg@163.com" fs:self.ecgRate chn:12 freqLpass:self.freq_low freqNotch:self.freq_notch smoothStrength:self.smoothStrength];
        //心率计算器
        self.meanRRmsLab = [[vhMeanRRmsLib alloc] initWithFs:self.ecgRate chn:12 freqNotch:self.freq_notch uVpb:self.uVpb];
    }
    return self;
}
- (NSMutableArray<NSMutableArray<NSNumber *> *> *)bufferData {
    if (!_bufferData) {
        _bufferData = [NSMutableArray arrayWithCapacity:12];
        for (int i = 0; i < 12; i++) {
            [_bufferData addObject:[NSMutableArray array]];
        }
    }
    return _bufferData;
}

///set rate
- (void)setFilterWithRate:(int)rate uVpb:(double)uVpb {
    if (self.ecgRate == rate && self.uVpb == uVpb) {
        return;
    }
    [self clearBuffer];
    self.ecgRate = rate;
    self.uVpb = uVpb;
    [self updateVhFilterLibData];
    [self upDateVhMeanRRms];
}
/// set low
- (void)setFilterFreqLow:(kFreqLowType)freqLow {
    if (self.freq_low == freqLow) {
        return;
    }
    self.freq_low = (int)freqLow;
    [self updateVhFilterLibData];
}
/// set ac
- (void)setFilterFreqNotch:(kFreqNotchType)freqNotch {
    if (self.freq_notch == freqNotch) {
        return;
    }
    self.freq_notch = (int)freqNotch;
    [self updateVhFilterLibData];
    [self upDateVhMeanRRms];
}
/// set mooth
- (void)setFilterFreqMooth:(kSmoothType)freqMooth {
    if (self.smoothStrength == freqMooth) {
        return;
    }
    self.smoothStrength = (int)freqMooth;
    [self updateVhFilterLibData];
}
/// set filter switch
- (void)setFilterSwitch:(BOOL)isOpen {
    self.isOpen = isOpen;
    [self.filterLab switchFiltersOnOffLpass:isOpen onOffNotch:isOpen onOffSmooth:isOpen];
}

- (void)filtersECGsData:(NSArray <NSArray <NSNumber *>*>* _Null_unspecified)ECGs dataHandler:(void(^)(NSArray <NSArray <NSNumber *>*>* _Nullable ecgData))handler hbrHandler:(void(^)(int hbr))hbrHandler rrmsHandler:(void(^)(int rrms))rrmsHandler {
    if(ECGs == nil || ECGs.firstObject.count <= 0 || ECGs.count < 12){
        return;
    }
    
    for (int i = 0; i< ECGs.firstObject.count; i++) {
        NSMutableArray *tempArr = [NSMutableArray arrayWithCapacity:0];
        [tempArr addObject:ECGs[0][i]];
        [tempArr addObject:ECGs[1][i]];
        [tempArr addObject:ECGs[2][i]];
        [tempArr addObject:ECGs[3][i]];
        [tempArr addObject:ECGs[4][i]];
        [tempArr addObject:ECGs[5][i]];
        [tempArr addObject:ECGs[6][i]];
        [tempArr addObject:ECGs[7][i]];
        [tempArr addObject:ECGs[8][i]];
        [tempArr addObject:ECGs[9][i]];
        [tempArr addObject:ECGs[10][i]];
        [tempArr addObject:ECGs[11][i]];
        
        [self getHBRAndRRmsWithECGs:tempArr hbrHandler:hbrHandler rrmsHandler:rrmsHandler];
        [self filtersSingleData:tempArr handler:handler];
    }
}
#pragma mark - HR and RR
- (void)getHBRAndRRmsWithECGs:(NSArray <NSNumber *>*)ECGs hbrHandler:(void(^)(int hbr))hbrHandler rrmsHandler:(void(^)(int rrms))rrmsHandler {
    if (ECGs.count < 12){
        return;
    }
    NSMutableArray *target = [[NSMutableArray alloc] init];
    NSInteger i = 0;
    while (target.count < 12) {
        [target addObject:[self checkNumber:[ECGs objectAtIndex:i]]];
        i++;
    }
    //获取hr
    short hbr = [self meanHRLibWithData:target];
    if (hbr > 0) {
        !hbrHandler?:hbrHandler(hbr);
    }
//    //获取rrms
//    short rrms = [self meanRRmsLibWithData:target];
//    if (rrms > 0) {
//        !rrmsHandler?:rrmsHandler(rrms);
//    }
}
- (void)filtersSingleData:(NSArray <NSNumber *> *)ECGs handler:(void (^)(NSArray<NSArray<NSNumber *> *> * _Nullable))handler{
    
    NSArray <NSNumber *>* lead_List = [self filtersLibWithData:ECGs];
    if (lead_List == nil || lead_List.count < 12){
        return;
    }
    [self.bufferData[0] addObject:lead_List[0]];
    [self.bufferData[1] addObject:lead_List[1]];
    [self.bufferData[2] addObject:lead_List[2]];
    [self.bufferData[3] addObject:lead_List[3]];
    [self.bufferData[4] addObject:lead_List[4]];
    [self.bufferData[5] addObject:lead_List[5]];
    [self.bufferData[6] addObject:lead_List[6]];
    [self.bufferData[7] addObject:lead_List[7]];
    [self.bufferData[8] addObject:lead_List[8]];
    [self.bufferData[9] addObject:lead_List[9]];
    [self.bufferData[10] addObject:lead_List[10]];
    [self.bufferData[11] addObject:lead_List[11]];
    if ([self.bufferData firstObject].count >= 80) {
        !handler?:handler(self.bufferData);
        [self clearBuffer];
    }
}

- (void)clearBuffer {
    for (NSMutableArray *channel in self.bufferData) {
        [channel removeAllObjects];
    }
}

#pragma mark - private -
/// Do Filters
/// \param data a group 12-lead sampling data or 8-lead. the number of data is the number of leads
///
///
/// returns:
///
/// <ul>
///   <li>
///     filtered data
///   </li>
/// </ul>
- (NSArray<NSNumber *> * _Nullable)filtersLibWithData:(NSArray<NSNumber *> * _Nonnull)data {
    @try {
        return [self.filterLab filtersWithData:data];
    } @catch (NSException *exception) {
        NSLog(@"Error:%@", exception.description);
    } @finally {
    }
}

- (int16_t)meanRRmsLibWithData:(NSArray<NSNumber *> * _Nonnull)data {
    return [self.meanRRmsLab meanRRmsWithData:data];
}

- (int16_t)meanHRLibWithData:(NSArray<NSNumber *> * _Nonnull)data {
    return [self.meanRRmsLab meanHRWithData:data];
}

- (void)updateVhFilterLibData {
    BOOL ok = [self.filterLab updateWithFs:self.ecgRate freqLpass:self.freq_low freqNotch:self.freq_notch smoothStrength:self.smoothStrength];
    if(!ok){
        NSLog(@"update ecg filter error");
    }
}
//初始化创建心率分析核心对象是否成功, warn：先有心电数据才可创建
- (void)upDateVhMeanRRms {
     [self.meanRRmsLab createWithFs:self.ecgRate chn:12 freqNotch:self.freq_notch uVpb:self.uVpb];
}

-(NSNumber *)checkNumber:(NSNumber *)value {
    //short 数据指针的数值范围容错处理 开始
    if ([value intValue] < -32768){
        value = [NSNumber numberWithShort:-32768];
    }else if ([value intValue] > 32767){
        value = [NSNumber numberWithShort:32767];
    }
    return value;
}
@end

